package com.banmajio.service.impl;

import com.banmajio.bean.Kde03;
import com.banmajio.bean.Kdp01;
import com.banmajio.mapper.Kde03Mapper;
import com.banmajio.mapper.Kdp01Mapper;
import com.banmajio.mapper.XtVolunteerInfoMapper;
import com.banmajio.pojo.VolunteerTrajectory;
import com.banmajio.mapper.*;
import com.banmajio.pojo.XtVoluntaryOrg;
import com.banmajio.pojo.XtVolunteerInfo;
import com.banmajio.service.DataTransService;
import com.banmajio.util.DateUtils;
import com.baomidou.dynamic.datasource.annotation.DS;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;

@Slf4j
@Service
public class DataTransServiceImpl implements DataTransService {

    @Autowired
    private Kde03Mapper kde03Mapper;

    @Autowired
    private Kdp01Mapper kdp01Mapper;

    @Autowired
    private Kdx07Mapper kdx07Mapper;

    @Autowired
    private Kde06Mapper kde06Mapper;

    @Autowired
    private XtVoluntaryOrgMapper xtVoluntaryOrgMapper;

    @Autowired
    private MyVoluntaryOrgMapper myVoluntaryOrgMapper;

    @Autowired
    private XtVolunteerInfoMapper xtVolunteerInfoMapper;

//    @Autowired
//    private DataTransService dataTransService;

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    @Autowired
    private  ThreadPoolTaskExecutor dataMigrationExecutor;

    // 缓存队列（线程安全）
    private final Queue<Long> idCache = new ConcurrentLinkedQueue<>();
    private static final int CACHE_SIZE = 100000; // 缓存大小
    // 初始化（单例，建议在配置类中注入）
    private static final Snowflake snowflake = IdUtil.createSnowflake(1, 1); // workerId=1, datacenterId=1


    @Override
    public void printDataKde03() {
        long l = System.currentTimeMillis();
        // 总条数
        Integer count = kde03Mapper.getCount();
        // 手动分页处理 一次处理1000条数据
        Integer page = count / 1000;
        for (int i = 0; i <= page; i++) {
            List<Kde03> byPage = kde03Mapper.getByPage(i);
            if (!CollectionUtils.isEmpty(byPage)) {
                List<String> collect = byPage.stream().map(Kde03::getAlbe0302).collect(Collectors.toList());
                log.info("第{}页数据:{}", i+1, collect);
                // todo process data, sync database
                log.info("第{}页数据处理完成", i+1);
            }
        }
        log.info("处理：{}条数据，共计耗时：{}秒", count, (System.currentTimeMillis() - l) / 1000);
    }

    @Override
    public void printDataKdp01() {
        long l = System.currentTimeMillis();
        // 总条数
        Integer count = kdp01Mapper.getCount();
        // 手动分页处理 一次处理1000条数据
        Integer page = count / 1000;
        for (int i = 0; i <= page; i++) {
            List<Kdp01> byPage = kdp01Mapper.getByPage(i);
            if (CollectionUtils.isEmpty(byPage)) {
                log.info("未查询到数据");
            }
            List<String> collect = byPage.stream().map(Kdp01::getAxcp0002).collect(Collectors.toList());
            log.info("第{}页数据:{}", i+1, collect);
            // todo process data, sync database
            for (Kdp01 kdp01 : byPage) {

            }
            log.info("第{}页数据处理完成", i+1);
        }
        log.info("处理：{}条数据，共计耗时：{}秒", count, (System.currentTimeMillis() - l) / 1000);
    }

    @Override
    @DS("master") // 指定写操作使用主数据源
    public void getKdp01List() {
        long l = System.currentTimeMillis();
        // 总条数
        Integer count = kdp01Mapper.getCount();
        // 手动分页处理 一次处理1000条数据
        Integer page = count / 1000;
        for (int i = 0; i <= page; i++) {
            List<Kdp01> byPage = kdp01Mapper.getByPage(i * 1000);
            if (CollectionUtils.isEmpty(byPage)) {
                log.info("未查询到数据");
            }
            // trans data
            this.insertVolunteerInfo(byPage);
        }
        log.info("共处理数据：{}条，耗时：{}秒", count, (System.currentTimeMillis() - l) / 60);
    }

    @DS("slave") // 指定写操作使用主数据源
    public void insertVolunteerInfo(List<Kdp01> kdp01List) {
        if (CollectionUtils.isEmpty(kdp01List)) {
            return;
        }
        List<XtVolunteerInfo> xtVolunteerInfoList = new ArrayList<>();
        for (Kdp01 kdp01 : kdp01List) {
            XtVolunteerInfo volunteerInfo = new XtVolunteerInfo();
            volunteerInfo.setId(Long.valueOf("100000000" + xtVolunteerInfoMapper.getId()));// 序列号生成
            volunteerInfo.setName(kdp01.getAxcp0002());
            volunteerInfo.setIdType(01);// todo 待转换
            volunteerInfo.setUsername(kdp01.getAxcp0005());
            volunteerInfo.setIdNumber(kdp01.getAxcp0005());
            volunteerInfo.setSex(Integer.valueOf(kdp01.getAxcp0006())); // 1-男 2-女
            volunteerInfo.setNationality(kdp01.getAxcp0007());// 国籍
            volunteerInfo.setNation(kdp01.getAxcp0008());// 非必填
            volunteerInfo.setServiceArea(kdp01.getAxaa0003() + "000");// 民政部只精确到区，后三位补零处理
            volunteerInfo.setServiceCategory(kdp01.getAlbp0206());// todo 待转换
            volunteerInfo.setCreateTime(DateUtils.formatYMD(kdp01.getAxbe0031()));
            volunteerInfo.setPoliticsStatus(kdp01.getAxcp0017());
            volunteerInfo.setMobile(kdp01.getAxcp0037());// or axzx0001
            volunteerInfo.setDateOfBirth(kdp01.getAxcp0039().substring(0, 10));
            volunteerInfo.setDeletionStatus(1);// 待转换
            volunteerInfo.setEmail(kdp01.getAxzx0005());
            xtVolunteerInfoList.add(volunteerInfo);
        }
        try {
            Integer integer = xtVolunteerInfoMapper.batchInsert(xtVolunteerInfoList);
        } catch (Exception e) {
            log.error("批量插入数据库报错，e:", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 插入轨迹表数据
     */
    /**
     * 批量插入志愿者轨迹数据（每1000条一批）
     */
    public Integer insertTrackData(List<Long> userIdList) {
        if (userIdList == null || userIdList.isEmpty()) {
            return 0;
        }

        // 每批处理1000条
        final int batchSize = 1000;
        int totalInserted = 0;

        for (int i = 0; i < userIdList.size(); i += batchSize) {
            List<Long> batchUserIdList = userIdList.subList(
                    i,
                    Math.min(i + batchSize, userIdList.size())
            );

            List<VolunteerTrajectory> trajectoryList = batchUserIdList.stream()
                    .map(userId -> {
                        VolunteerTrajectory trajectory = new VolunteerTrajectory();
                        trajectory.setUserId(userId);
                        trajectory.setCode("REGISTER");
                        trajectory.setDescription("用户注册轨迹");
                        trajectory.setDetail("用户成功注册成为志愿者");
                        trajectory.setCreateTime(LocalDateTime.now());
                        return trajectory;
                    })
                    .collect(Collectors.toList());

            try {
                // 使用MyBatis-Plus的批量插入方法
//                boolean success = xtVolunteerInfoMapper.saveBatch(trajectoryList);
//                if (success) {
//                    totalInserted += trajectoryList.size();
//                }
            } catch (Exception e) {
                log.error("批量插入失败，批次索引: {}", i, e);
                // 根据业务需求决定是否继续处理后续批次
                throw new RuntimeException("批量插入失败", e);
            }
        }

        return totalInserted;
    }


    /**
     * kde03志愿服务队伍基本信息表-->> insert -->> xt_voluntary_org志愿团体
     */
    @Override
    @DS("slave") // 从库读数据
    public void getKde03List() {
        long startTime = System.currentTimeMillis();
        Integer count = kde03Mapper.getCount();
        log.info("开始迁移数据，总记录数：{}", count);

        if (count <= 0) {
            return;
        }

        // 配置参数
        int batchSize = 5000; // 每批次处理5000条
        Integer totalPages = (count + batchSize - 1) / batchSize; // 向上取整
        int maxConcurrentBatches = 20; // 最大并发批次数，应与线程池大小匹配

        // 进度跟踪
        AtomicInteger processedCount = new AtomicInteger(0);
        AtomicInteger successBatches = new AtomicInteger(0);
        AtomicInteger failedBatches = new AtomicInteger(0);
        AtomicBoolean hasFatalError = new AtomicBoolean(false); // 标记是否有致命错误

        // 使用信号量控制并发任务数量
        Semaphore semaphore = new Semaphore(maxConcurrentBatches);

        log.info("开始分批处理数据，每批 {} 条，共 {} 批", batchSize, totalPages);

        // 顺序处理批次，控制并发量
        for (int i = 0; i < totalPages && !hasFatalError.get(); i++) {
            final int pageNum = i;

            try {
                // 尝试获取许可，如果没有可用许可则阻塞
                semaphore.acquire();

                // 提交任务到线程池
                CompletableFuture.runAsync(() -> {
                            try {
                                if (hasFatalError.get()) {
                                    return; // 如果已存在致命错误，直接退出
                                }

                                processBatch(pageNum, batchSize, processedCount);
                                successBatches.incrementAndGet();

                                // 每处理10个批次，记录一次总体进度
                                if (successBatches.get() % 10 == 0 || pageNum == totalPages - 1) {
                                    log.info("已处理：{}条，进度：{}/{}，成功批次：{}，失败批次：{}",
                                            processedCount.get(), pageNum + 1, totalPages,
                                            successBatches.get(), failedBatches.get());
                                }
                            } catch (Exception e) {
                                log.error("处理批次失败，页码：{}", pageNum, e);
                                failedBatches.incrementAndGet();

                                // 可以根据具体情况决定是否为致命错误
                                if (isFatalError(e)) {
                                    hasFatalError.set(true);
                                    log.error("检测到致命错误，停止数据迁移");
                                }
                            } finally {
                                semaphore.release(); // 释放许可
                            }
                        }, dataMigrationExecutor)
                        .exceptionally(ex -> {
                            log.error("异步任务执行异常，批次：{}", pageNum, ex);
                            failedBatches.incrementAndGet();
                            if (isFatalError(ex)) {
                                hasFatalError.set(true);
                                log.error("检测到致命错误，停止数据迁移");
                            }
                            semaphore.release(); // 释放许可
                            return null;
                        });

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.error("获取信号量时被中断", e);
                hasFatalError.set(true);
                break;
            } catch (RejectedExecutionException e) {
                // 处理线程池拒绝异常
                log.error("线程池暂时无法接受新任务，批次 {}", pageNum, e);
                i--; // 重新尝试当前批次
                try {
                    Thread.sleep(1000); // 等待1秒后重试
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    log.error("等待时被中断", ie);
                    hasFatalError.set(true);
                    break;
                }
            } catch (Exception e) {
                log.error("提交批次任务时发生未知异常，批次 {}", pageNum, e);
                failedBatches.incrementAndGet();
                if (isFatalError(e)) {
                    hasFatalError.set(true);
                    log.error("检测到致命错误，停止数据迁移");
                    break;
                }
            }
        }

        // 等待所有剩余任务完成
        try {
            // 给一个合理的超时时间，确保所有任务都有机会完成
            Thread.sleep(30000); // 等待30秒
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("等待剩余任务完成时被中断", e);
        }

        long endTime = System.currentTimeMillis();
        log.info("数据迁移结束！共处理：{}条，成功批次：{}，失败批次：{}，耗时：{}秒",
                processedCount.get(), successBatches.get(), failedBatches.get(),
                (endTime - startTime) / 1000.0);

        // 如果有失败批次，记录警告
        if (failedBatches.get() > 0) {
            log.warn("数据迁移过程中存在失败批次，请注意检查！");
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @DS("master")
    public void processBatch(int pageNum, int batchSize, AtomicInteger processedCount) {
        try (SqlSession batchSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
            XtVoluntaryOrgMapper mapper = batchSession.getMapper(XtVoluntaryOrgMapper.class);

            List<Kde03> pageData = kde03Mapper.getByPage(pageNum * batchSize, batchSize);
            if (CollectionUtils.isEmpty(pageData)) {
                return;
            }

            List<XtVoluntaryOrg> orgList = convertToOrgList(pageData);

            int batchCount = 0;
            for (XtVoluntaryOrg org : orgList) {
                mapper.insert(org);
                batchCount++;

                // 每5000条提交一次，避免内存溢出
                if (batchCount % 5000 == 0) {
                    batchSession.flushStatements();
                }
            }

            batchSession.commit();
            batchSession.clearCache();

            int count = processedCount.addAndGet(pageData.size());
            if (count % (batchSize * 10) == 0) {
                log.info("已处理：{}条，进度：{}/{}", count, pageNum + 1, (processedCount.get() + batchSize - 1) / batchSize);
            }
        } catch (Exception e) {
            throw new RuntimeException("批次处理失败，页码：" + pageNum, e);
        }
    }

    private List<XtVoluntaryOrg> convertToOrgList(List<Kde03> kde03List) {
        List<XtVoluntaryOrg> result = new ArrayList<>(kde03List.size());
        for (Kde03 kde03 : kde03List) {
            XtVoluntaryOrg org = new XtVoluntaryOrg();
            org.setId(getSnowflakeId());
//            org.setId(snowflake.nextId());
            // 基础信息 - 非空校验
            if (kde03.getAlbe0302() != null) {
                org.setName(kde03.getAlbe0302()); // 队伍名称
            }
            org.setParentId(0L);
            // 队伍类型映射
            org.setRegisterType(mapRegisterType(kde03.getAlbe0303()));// 码值 todo
            if (kde03.getAxbe1307() != null) {
                org.setRegistrationOrg(kde03.getAxbe1307()); // 登记/备案机构
            }
            org.setOrgCode("");
            org.setSealImg("");
            if (kde03.getAxbe1313() != null) {
                org.setAddress(kde03.getAxbe1313()); // 详细地址
            }else {
                org.setAddress(""); // 详细地址
            }
            if (kde03.getAxbe0015() != null) {
                org.setEstablishedDate(parseDate(kde03.getAxbe0015())); // 成立日期
            }
            // 团体人数 - 优化空值和格式校验
            String teamNumbersStr = kde03.getAlbe0312();
            if (teamNumbersStr != null && !teamNumbersStr.isEmpty()) {
                try {
                    org.setTeamNumbers(Integer.valueOf(teamNumbersStr));
                } catch (NumberFormatException e) {
                    log.error("团体人数格式错误: {}", teamNumbersStr, e);
                    org.setTeamNumbers(0); // 默认值
                }
            } else {
                org.setTeamNumbers(0);
            }
            if (kde03.getAlbe0316() != null) {
                org.setDescription(kde03.getAlbe0316()); // 简要描述
            }
            if (kde03.getAxzx0007() != null) {
                org.setContractName(kde03.getAxzx0007()); // 联系人姓名
            }else {
                org.setContractName(""); // 联系人姓名
            }
            if (kde03.getAxzx0008() != null) {
                org.setContractMobile(kde03.getAxzx0008()); // 联系人手机
            }else {
                org.setContractMobile(""); // 联系人姓名
            }
            org.setContractTelephone("");
//            if (kde03.getAlbp0206() != null) {
//                org.setServiceCategory(kde03.getAlbp0206()); // 服务类别  todo
//            }else {
                org.setServiceCategory("");
//            }
            org.setParentName("");
            org.setRegistrationCode("");
            if (kde03.getAxbe1311() != null) {
                org.setCompetentOrg(kde03.getAxbe1311()); // 主管单位名称
            }
            org.setCompetentOrgType(""); // 主管单位类型
            if (kde03.getAxbe0028() != null) {
                org.setArea(kde03.getAxbe0028()); // 区域
            }else {
                org.setArea("");
            }
            // 团队累计志愿服务时间 - 使用之前优化的方法
            org.setTotalServiceHour(parseServiceHour(kde03.getAlbe0369()));
            if (kde03.getAxbe1307() != null) {
                org.setRegistrationOrgan(kde03.getAxbe1307()); // 登记机关
            }
            if (kde03.getAxbe0002() != null) {
                org.setUnifiedSocialCreditCode(kde03.getAxbe0002()); // 统一社会信用代码
            }
            org.setSocialOrgType("");

            if (kde03.getAxbe0031() != null) {
                org.setCreateTime(parseDate(kde03.getAxbe0031())); // 创建时间
            }else {
                org.setCreateTime(new Date()); // 创建时间
            }
            if (kde03.getUpdate_time() != null) {
                org.setUpdateTime(parseDate(kde03.getUpdate_time())); // 更新时间
            }else {
                org.setUpdateTime(new Date()); // 更新时间
            }
            // 团队状态 - 使用之前优化的方法
            org.setStatus(safeParseInteger(kde03.getAxbe1354()));
            org.setPublicMobile(0); // 是否公开联络人手机号
            if (kde03.getAxzx0009() != null) {
                org.setEmail(kde03.getAxzx0009()); // 电子邮箱
            }
            org.setBusinessGuidanceOrg("0"); // 业务指导单位名称
            // 是否公开 - 使用安全转换方法
            org.setIsPublic(safeParseInteger(kde03.getAxbe1327()));
            org.setJoinMode("100"); // 申请方式
            if (kde03.getAxbe1313() != null) {
                org.setAreaPath(kde03.getAxbe1313()); // 区域全路径
            }else {
                org.setAreaPath("");
            }
            // 纬度/经度 - 使用之前优化的方法
            org.setLat(parseBigDecimal(kde03.getAlbe0315()));
            org.setLng(parseBigDecimal(kde03.getAlbe0314()));
            org.setAreaGroup("");
            org.setUsername("");
            org.setPassword("");
            // 禁止状态 - 使用安全转换方法
            org.setTabooStatus(safeParseInteger(kde03.getAxbe1391()));
            org.setNums(0);
            org.setDeletionStatus(0);
            result.add(org);
        }
        return result;
    }


    private Integer mapRegisterType(String teamType) {
        // 根据实际业务逻辑映射队伍类型到登记类型
        if ("1".equals(teamType)) {
            return 200; // 映射为"在民政登记的法人社会组织"
        }
        return 100; // 默认"未登记的志愿服务组织"
    }

    /**
     * 字符串转Date
     */
    private Date parseDate(String dateStr) {
        if (dateStr == null || dateStr.trim().isEmpty()) {
            return null;
        }

        try {
            // 处理常见日期格式，可根据实际情况调整
            if (dateStr.contains("-")) {
                return new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
            } else if (dateStr.contains("/")) {
                return new SimpleDateFormat("yyyy/MM/dd").parse(dateStr);
            } else if (dateStr.matches("\\d{8}")) {
                return new SimpleDateFormat("yyyyMMdd").parse(dateStr);
            } else if (dateStr.length() > 10) {
                // 包含时间的格式
                return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateStr);
            }
        } catch (ParseException e) {
            log.error("日期解析失败，字符串: {}", dateStr, e);
        }

        return null;
    }

    /**
     * 字符串转BigDecimal，并确保精度为6位小数
     * @param value 输入字符串
     * @return 转换后的BigDecimal，保留6位小数，四舍五入
     */
    private BigDecimal parseBigDecimal(String value) {
        if (value == null || value.trim().isEmpty() || "NULL".equalsIgnoreCase(value.trim())) {
            return BigDecimal.ZERO; // 处理空值
        }
        try {
            // 移除千分位逗号等非数字字符（可选，根据输入格式决定）
            String cleanValue = value.trim().replaceAll(",", "");

            // 转换为BigDecimal
            BigDecimal decimal = new BigDecimal(cleanValue);

            // 关键优化：设置精度为6位小数，使用四舍五入模式
            return decimal.setScale(6, RoundingMode.HALF_UP);

        } catch (NumberFormatException e) {
            log.error("数值格式错误，无法转换为BigDecimal: {}", value, e);
            return BigDecimal.ZERO; // 或根据业务需求返回 null 或抛出异常
        }
    }

    private Long parseServiceHour(String value) {
        if (value == null || value.trim().isEmpty()) {
            log.debug("服务时间为空，使用默认值0分钟");
            return 0L;
        }

        try {
            // 直接转换为分钟并四舍五入
            BigDecimal minutes = new BigDecimal(value.trim())
                    .multiply(new BigDecimal("60"));

            Long result = minutes.setScale(0, RoundingMode.HALF_UP).longValue();

            // 记录转换过程，便于调试
            log.debug("服务时间转换: {}小时 → {}分钟", value, result);
            return result;
        } catch (NumberFormatException e) {
            log.error("服务时间格式错误，原始值: {}", value, e);
            return 0L;
        }
    }

    private Integer safeParseInteger(String value) {
        if (value == null || value.isEmpty()) {
            return 1; // 返回默认值
        }
        try {
            return Integer.valueOf(value);
        } catch (NumberFormatException e) {
            log.error("状态值格式错误: {}", value, e);
            return 1; // 或返回默认值
        }
    }

    private long getSnowflakeId() {
        Long id = idCache.poll();
        if (id == null) {
            // 批量生成补充缓存（加锁避免并发生成）
            synchronized (this) {
                if (idCache.size() < 1000) {
                    for (int i = 0; i < CACHE_SIZE; i++) {
                        idCache.add(snowflake.nextId());
                    }
                }
            }
            id = idCache.poll();
        }
        return id;
    }


    /**
     * 判断是否为致命错误（需要终止整个迁移过程的严重异常）
     * 致命错误通常指：系统资源耗尽、核心服务不可用、数据一致性无法保证的异常
     */
    private boolean isFatalError(Throwable t) {
        // 1. 系统级资源耗尽（必须终止，否则可能导致系统崩溃）
        if (t instanceof OutOfMemoryError) {
            return true;
        }
        if (t instanceof StackOverflowError) {
            return true;
        }
        if (t instanceof VirtualMachineError) { // 虚拟机错误（如内存不足、线程限制等）
            return true;
        }

        // 2. 数据库核心连接异常（连接彻底不可用，重试也无法恢复）
        if (t instanceof SQLException) {
            SQLException sqlEx = (SQLException) t;
            String sqlState = sqlEx.getSQLState();
            // SQLState以"08"开头：连接异常（如连接被拒绝、断开、超时且无法重试）
            // 参考：https://www.postgresql.org/docs/current/errcodes-appendix.html
            if (sqlState != null && sqlState.startsWith("08")) {
                return true;
            }
            // 数据库严重错误（如磁盘满、权限丢失）
            if (sqlState != null && (sqlState.startsWith("53") || // 资源不足（如磁盘满）
                    sqlState.startsWith("55") || // 对象状态异常（如表损坏）
                    sqlState.startsWith("58") || // 系统错误（如内部故障）
                    sqlState.startsWith("28"))) { // 权限错误（无法执行核心操作）
                return true;
            }
        }
        // 3. 线程/并发框架致命异常（线程池崩溃，无法继续提交任务）
        if (t instanceof RejectedExecutionException) {
            // 线程池彻底拒绝任务（如已关闭、队列满且无法扩容），无法继续处理批次
            return true;
        }
        if (t instanceof InterruptedException && Thread.currentThread().isInterrupted()) {
            // 线程被中断且无法恢复，迁移流程被强制终止
            return true;
        }

        // 非致命错误（如单条数据格式错误、临时网络波动等，可重试或跳过）
        return false;
    }


}
